/*
  路径规划组件：

 */
import axios from 'axios'
import * as Cesium from 'cesium'
import { AMapKey } from '@/api/request.js'

// 高德地图路径规划的api地址   默认为AMap
const AMapRoutePlanApi = 'https://restapi.amap.com/v3/direction/driving'
// 高德地图申请的key
// const AMapKey = '59ad928397c6e2c7d507b2d0089d16eb'

const startPointImg64 =
  ''
const endPointImg64 =
  ''

export const getPlanPaths = (params = {}) => {
  /*
    params  上传参数格式
    start:[0,1] //路径起点  0项为经度  1项为纬度
    end:[0,1] //路径终点  0项为经度  1项为纬度

    ********************************************
    此处返回的数据坐标系为：火星坐标系 gcj , 使用时需要转换为世界坐标系 wgs
    *******************************************
  */
  const { start = [], end = [] } = params
  let startp = wgs2gcj(start)
  let endp = wgs2gcj(end)
  const origin = (startp[0] || '') + ',' + (startp[1] || '')
  const destination = (endp[0] || '') + ',' + (endp[1] || '')
  params = {
    output: 'json', // 返回数据格式类型 可选值：JSON，XML
    key: AMapKey, // 高德地图应用申请的key
    origin,
    destination
  }

  return new Promise((resolve, reject) => {
    axios
      .get(AMapRoutePlanApi, {
        params
      })
      .then(
        response => {
          // let data = response.data
          // data.route.paths[0] &&
          //   data.route.paths[0].steps &&
          //   data.route.paths[0].steps.forEach(item => {
          //     let positionStr = item.polyline
          //     let strArr = positionStr.split(';')
          //     let polylineStr = ''
          //     for (let z = 0; z < strArr.length; z++) {
          //       let item2 = strArr[z]
          //       let strArr2 = item2.split(',')
          //       let p = gcj2wgs(strArr2)
          //       polylineStr += ';' + p.join(',')
          //     }
          //     polylineStr = polylineStr.substr(1)
          //     item.polyline = polylineStr
          //   })
          resolve(response.data)
        },
        err => {
          reject(err)
        }
      )
      .catch(error => {
        reject(error)
      })
  })
}

// 绘制路线
export const addRouteLine = (res, viewer) => {
  let arr = []
  let steps = res.steps
  let drawingColor = '#41D4F3' // 默认为湖蓝色
  let lineWidth = 14 // 路线的宽度 默认为 4
  let borderStyle = 'dashed' // 绘制的图形的样式  solid：实线  dashed ：虚线
  for (let i = 0; i < steps.length; i++) {
    let item = steps[i]
    let positionStr = item.polyline
    let strArr = positionStr.split(';')
    for (let z = 0; z < strArr.length; z++) {
      let item2 = strArr[z]
      let strArr2 = item2.split(',')
      let p = gcj2wgs(strArr2)
      arr.push(p)
    }
  }
  let cartesians = lnglatArrToCartesianArr(arr)
  let linePolylineMaterial
  if (borderStyle === 'solid') {
    linePolylineMaterial = Cesium.Color.fromCssColorString(drawingColor)
  } else if (borderStyle === 'dashed') {
    linePolylineMaterial = new Cesium.PolylineArrowMaterialProperty(Cesium.Color.fromCssColorString(drawingColor))
  }

  return viewer.entities.add({
    polyline: {
      positions: cartesians,
      width: lineWidth,
      material: linePolylineMaterial
    }
  })
}

// cesium 地图绘制地图路线
export const drawRoutePlan = (viewer, options = {}) => {
  /*
    参数说明：
      1. viewer  //地图查看器
      2. options 绘制路线的配置
        color  绘制的样式的颜色  默认为红
        width 绘制线条的宽度  默认为 4px
        borderStyle 绘制的图形的样式  solid：实线  dashed ：虚线
        startPoint： 起始点   [] 经纬度
        endPoint ： 终点     [] 经纬度
  */

  const {
    color: drawingColor = '#41D4F3', // 默认为湖蓝色
    width: lineWidth = 4, // 路线的宽度 默认为 4
    borderStyle = 'dashed', // 绘制的图形的样式  solid：实线  dashed ：虚线
    startPoint = [0, 0], // 起始点   经纬度
    endPoint = [0, 0] // 终点
  } = options

  // 将px 转换为 Catesian 中的 数值
  function getCatesian3FromPX (px, viewer, entity) {
    let pick = viewer.scene.pick(px)
    let cartesian
    let drillPick = viewer.scene.drillPick(px)
    let truePick = null
    if (entity) {
      for (let i = 0; i < drillPick.length; i++) {
        if (drillPick[i].id._id != entity.id) {
          truePick = drillPick[i].id
          break
        }
      }
    } else {
      truePick = pick
    }
    if (viewer.scene.pickPositionSupported && Cesium.defined(truePick)) {
      cartesian = viewer.scene.pickPosition(px)
    } else {
      let ray = viewer.camera.getPickRay(px)
      if (!ray) return
      cartesian = viewer.scene.globe.pick(ray, viewer.scene)
    }
    return cartesian
  }

  // 将cartesian中的数据转换成经纬度
  function cartesianToLnglat (cartesian, isToWgs84) {
    if (!cartesian) return
    let ellipsoid = viewer.scene.globe.ellipsoid
    let lnglat = ellipsoid.cartesianToCartographic(cartesian)
    // var cartographic = Cesium.Cartographic.fromCartesian(cartesian);
    if (isToWgs84) {
      let lat = Cesium.Math.toDegrees(lnglat.latitude)
      let lng = Cesium.Math.toDegrees(lnglat.longitude)
      let hei = lnglat.height
      return [lng, lat, hei]
    } else {
      return [lnglat.longitude, lnglat.latitude, lnglat.height]
    }
  }

  // // 坐标处理
  class SearchRoute {
    constructor (start, end) {
      this.startP = start
      this.endP = end
    }

    start (opt) {
      let startP = wgs2gcj(this.startP)
      let endP = wgs2gcj(this.endP)
      getPlanPaths({
        start: startP,
        end: endP
        // start: this.startP,
        // end: this.endP
      })
        .then(json => {
          // 由于线涉及坐标较多 此处返回的坐标 未转为wgs84
          let data = ''
          if (!json || !json.route || !json.route.paths) {
            data = ''
          } else {
            data = json.route.paths
          }
          opt.callback(data)
        })
        .catch(err => {
          console.error(err)
        })
    }
  }

  // 处理用户输入事件。可以添加自定义功能以在以下位置执行当用户输入输入时。
  let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas) // viewer.scene.canvas => 用于为其创建场景的HTML canvas元素。
  let isClickAgain = false
  let start = null
  let end = null
  let scene = viewer.scene

  function draw () {
    // 绘制路线
    start = viewer.entities.add({
      // 起始点
      name: '起点',
      position: Cesium.Cartesian3.fromDegrees(startPoint[0], startPoint[1]),
      billboard: {
        image: startPointImg64,
        scale: 1,
        horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM
      }
    })

    end = viewer.entities.add({
      // 结束点
      name: '终点',
      position: Cesium.Cartesian3.fromDegrees(endPoint[0], endPoint[1]),
      billboard: {
        image: endPointImg64,
        scale: 1,
        horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM
      }
    })

    showRes(start.position.getValue(), end.position.getValue())
  }

  draw()

  // 鼠标左键单击开始绘制
  // handler.setInputAction(function(evt) {
  //   // 返回具有' primitive'属性的对象，该对象包含场景中的第一个（顶部）基本体在特定的窗口坐标处；
  //   var pick = viewer.scene.pick(evt.position)
  //   var cartesian = getCatesian3FromPX(evt.position, viewer)

  //   if (!isClickAgain) {
  //     isClickAgain = true

  //     start = viewer.entities.add({
  //       // 起始点
  //       name: '起点',
  //       position: cartesian,
  //       billboard: {
  //         image: startPointImg64,
  //         scale: 1,
  //         horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
  //         verticalOrigin: Cesium.VerticalOrigin.BOTTOM
  //       }
  //     })

  //     return
  //   }
  //   if (isClickAgain) {
  //     end = viewer.entities.add({
  //       // 结束点
  //       name: '终点',
  //       position: cartesian,
  //       billboard: {
  //         image: endPointImg64,
  //         scale: 1,
  //         horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
  //         verticalOrigin: Cesium.VerticalOrigin.BOTTOM
  //       }
  //     })

  //     showRes(start.position.getValue(), end.position.getValue())
  //     handler.destroy()
  //   }
  // }, Cesium.ScreenSpaceEventType.LEFT_CLICK)

  // 访问高德接口
  function showRes (start, end) {
    if (!start || !end) return
    let startp = cartesianToLnglat(start, true)
    let endP = cartesianToLnglat(end, true)
    let search = new SearchRoute([startp[0], startp[1]], [endP[0], endP[1]])
    search.start({
      strategy: 11,
      callback: function (data) {
        addRouteLine(data[0])
      }
    })
  }

  // 绘制路线
  function addRouteLine (res) {
    let arr = []
    let steps = res.steps
    for (let i = 0; i < steps.length; i++) {
      let item = steps[i]
      let positionStr = item.polyline
      let strArr = positionStr.split(';')
      for (let z = 0; z < strArr.length; z++) {
        let item2 = strArr[z]
        let strArr2 = item2.split(',')
        let p = gcj2wgs(strArr2)
        arr.push(p)
      }
    }
    let cartesians = lnglatArrToCartesianArr(arr)
    let linePolylineMaterial
    if (borderStyle === 'solid') {
      linePolylineMaterial = Cesium.Color.fromCssColorString(drawingColor)
    } else if (borderStyle === 'dashed') {
      linePolylineMaterial = new Cesium.PolylineArrowMaterialProperty(Cesium.Color.fromCssColorString(drawingColor))
    }

    viewer.entities.add({
      polyline: {
        positions: cartesians,
        width: lineWidth,
        material: linePolylineMaterial
      }
    })
  }
}
// 将经纬度转世界坐标 [101,40]
function lnglatToCartesian (lnglat) {
  if (!lnglat) return null
  return Cesium.Cartesian3.fromDegrees(lnglat[0], lnglat[1], lnglat[2] || 0)
}

// 将经纬度转换成Cartesian中的数组
function lnglatArrToCartesianArr (lnglatArr) {
  if (!lnglatArr) return []
  let arr = []
  for (let i = 0; i < lnglatArr.length; i++) {
    arr.push(lnglatToCartesian(lnglatArr[i]))
  }
  return arr
}
// 坐标转换==================================
let x_PI = (3.14159265358979324 * 3000.0) / 180.0
let PI = 3.1415926535897932384626
let a = 6378245.0
let ee = 0.00669342162296594323

function transformWD (lng, lat) {
  let ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng))
  ret += ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0) / 3.0
  ret += ((20.0 * Math.sin(lat * PI) + 40.0 * Math.sin((lat / 3.0) * PI)) * 2.0) / 3.0
  ret += ((160.0 * Math.sin((lat / 12.0) * PI) + 320 * Math.sin((lat * PI) / 30.0)) * 2.0) / 3.0
  return ret
}

function transformJD (lng, lat) {
  let ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng))
  ret += ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0) / 3.0
  ret += ((20.0 * Math.sin(lng * PI) + 40.0 * Math.sin((lng / 3.0) * PI)) * 2.0) / 3.0
  ret += ((150.0 * Math.sin((lng / 12.0) * PI) + 300.0 * Math.sin((lng / 30.0) * PI)) * 2.0) / 3.0
  return ret
}

function wgs2gcj (arrdata) {
  let lng = Number(arrdata[0])
  let lat = Number(arrdata[1])
  let dlat = transformWD(lng - 105.0, lat - 35.0)
  let dlng = transformJD(lng - 105.0, lat - 35.0)
  let radlat = (lat / 180.0) * PI
  let magic = Math.sin(radlat)
  magic = 1 - ee * magic * magic
  let sqrtmagic = Math.sqrt(magic)
  dlat = (dlat * 180.0) / (((a * (1 - ee)) / (magic * sqrtmagic)) * PI)
  dlng = (dlng * 180.0) / ((a / sqrtmagic) * Math.cos(radlat) * PI)
  let mglat = lat + dlat
  let mglng = lng + dlng

  mglng = Number(mglng.toFixed(6))
  mglat = Number(mglat.toFixed(6))
  return [mglng, mglat]
}

function gcj2wgs (arrdata) {
  let lng = Number(arrdata[0])
  let lat = Number(arrdata[1])
  let dlat = transformWD(lng - 105.0, lat - 35.0)
  let dlng = transformJD(lng - 105.0, lat - 35.0)
  let radlat = (lat / 180.0) * PI
  let magic = Math.sin(radlat)
  magic = 1 - ee * magic * magic
  let sqrtmagic = Math.sqrt(magic)
  dlat = (dlat * 180.0) / (((a * (1 - ee)) / (magic * sqrtmagic)) * PI)
  dlng = (dlng * 180.0) / ((a / sqrtmagic) * Math.cos(radlat) * PI)

  let mglat = lat + dlat
  let mglng = lng + dlng

  let jd = lng * 2 - mglng
  let wd = lat * 2 - mglat

  jd = Number(jd.toFixed(6))
  wd = Number(wd.toFixed(6))
  return [jd, wd]
}
